package org.htu.tinyspaces;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;

import org.htu.tinyspaces.api.TinySpace;
import org.htu.tinyspaces.impl.TinySpaceImpl;

/**
 * Initialises and provides a handle for our TinySpace.
 * @author rich.midwinter
 */
public final class TinySpaceFinder {
    /**
     * JNDI Lookup name.
     */
    private static final String LOOKUP_NAME = "TinySpaces";

    /**
     * JNDI port number.
     */
    private static final int PORT = 1099;

    /**
     * JNDI Context properties.
     */
    private static Hashtable<String,String> env;

    static {
        env = new Hashtable<String,String>();
        env.put(Context.INITIAL_CONTEXT_FACTORY,
                "com.sun.jndi.rmi.registry.RegistryContextFactory");
        env.put(Context.PROVIDER_URL, "rmi://localhost:1099");
    }

    /**
     * TinySpaceFinder constructor.
     */
    private TinySpaceFinder() {
        // We do not want to initialise this class.
    }

    /**
     * Retrieves a TinySpace, creating it if necessary.
     * @return A TinySpace instance.
     * @throws RemoteException For any remote exceptions.
     * @throws NamingException For any JNDI exceptions.
     */
    public static TinySpace find() throws RemoteException, NamingException {
        try {
            LocateRegistry.createRegistry(PORT);
        } catch (Exception e) {
            System.out.println("Registry already exists. That's fine.");
        }

        final Context ictx = new InitialContext(env);

        try {
            ictx.lookup(LOOKUP_NAME);
        } catch (NameNotFoundException nnfe) {
            ictx.bind(LOOKUP_NAME, new TinySpaceImpl());
        }

        return (TinySpace) ictx.lookup(LOOKUP_NAME);
    }

    /**
     * As for find(), but ensures creating a new TinySpace.
     * @return A TinySpace instance.
     * @throws RemoteException For any remote exceptions.
     * @throws NamingException For any JNDI exceptions.
     */
    public static TinySpace findNew() throws RemoteException, NamingException {
        final Context ictx = new InitialContext(env);

        try {
            ictx.unbind(LOOKUP_NAME);
        } catch (Exception e) {
            System.out.println("TinySpace doesn't exist. That's fine.");
        }

        return find();
    }
}
